package com.example.my_self_view.ratingbar

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import androidx.core.content.res.ResourcesCompat
import com.example.my_self_view.R
import kotlin.math.max

/**
 * @dsc     这种方法的 drawable 可以是vector、shape、layer-list，以及图片格式等
 * @Author  LiWeiZhong
 * @Date    2025/1/17 9:20
 * @Version 1.0
 */
class RatingBar2: View {

    private var gradeNumber: Int = 5
    private var imgSelected: Drawable? = ResourcesCompat.getDrawable(context.resources, R.drawable.star_selected, context.theme)
    private var imgUnselected: Drawable? = ResourcesCompat.getDrawable(context.resources, R.drawable.star_unselected, context.theme)

    private val intervalDip: Int = 3
    private var currentX = -1f
    private var currentGrade = 0
    private val xGradeList = arrayListOf<Float>() // 得分，开始的x

    constructor(context: Context): this(context, null) {}
    constructor(context: Context, attrs: AttributeSet?): this(context, attrs, 0) {}
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): this(context, attrs, defStyleAttr, 0) {}
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int): super(context, attrs, defStyleAttr, defStyleRes) {
        initAttrs(context, attrs)
        writeXGrade()
    }

    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        if (imgUnselected == null) throw Exception("未被选中默认资源不存在")
        if (imgSelected == null) throw Exception("被选中默认资源不存在")

        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatingBar2)
        typedArray.apply {
            try {
                gradeNumber = getInt(R.styleable.RatingBar2_gradeNumber2, gradeNumber)
                imgSelected = getDrawable(R.styleable.RatingBar2_imgSelected2)
                imgUnselected = getDrawable(R.styleable.RatingBar2_imgUnselected2)
            } finally {
                recycle()
            }
        }
    }

    private fun writeXGrade() {
        val unselectedInterval = imgUnselected!!.intrinsicWidth + dipToPx(intervalDip.toFloat())
        imgUnselected?.apply {
            for (i in 0 until gradeNumber) {
                xGradeList.add(i * unselectedInterval)
            }
        }
    }

    private fun drawableToBitmap(drawable: Drawable): Bitmap {
        // 1.获取宽高
        val width = drawable.intrinsicWidth
        val height = drawable.intrinsicHeight
        // 2.创建新的Bitmap
        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        // 3.创建新的canvas
        val canvas = Canvas(bitmap)
        // 4.设置 drawable 的边界
        drawable.setBounds(0, 0, canvas.width, canvas.height)
        // 5.使用 canvas 绘制到 bitmap 上
        drawable.draw(canvas)

        return bitmap
    }

    fun dipToPx(value: Float): Float {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, resources.displayMetrics)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)

        var width = MeasureSpec.getSize(widthMeasureSpec)
        var height = MeasureSpec.getSize(heightMeasureSpec)

        if (widthMode == MeasureSpec.AT_MOST) {
            var contentSelectedWidth = 0
            var contentUnselectedWidth = 0
            var contentWidth = 0
            if (imgSelected != null) contentSelectedWidth = imgSelected!!.intrinsicWidth
            if (imgUnselected != null) contentUnselectedWidth = imgUnselected!!.intrinsicWidth
            contentWidth = max(contentSelectedWidth, contentUnselectedWidth)
            width = contentWidth * 5 + (dipToPx(intervalDip.toFloat()) * 4).toInt() + paddingStart + paddingEnd
        }
        if (heightMode == MeasureSpec.AT_MOST) {
            var contentSelectedHeight = 0
            var contentUnselectedHeight = 0
            var contentHeight = 0
            if (imgSelected != null) contentSelectedHeight = imgSelected!!.intrinsicHeight
            if (imgUnselected != null) contentUnselectedHeight = imgUnselected!!.intrinsicHeight
            contentHeight = max(contentSelectedHeight, contentUnselectedHeight)
            height = contentHeight + paddingTop + paddingBottom
        }

        setMeasuredDimension(width, height)
    }

    override fun onDraw(canvas: Canvas) {
        val selectedInterval = imgSelected!!.intrinsicHeight + dipToPx(intervalDip.toFloat())
        var interval = 0f
        if (imgUnselected != null && imgSelected != null) {
            for (i in 0 until gradeNumber) {
                if (currentX >= interval) {
                    canvas.drawBitmap(drawableToBitmap(imgSelected!!), i * selectedInterval, 0f, null)
                } else canvas.drawBitmap(drawableToBitmap(imgUnselected!!), i * selectedInterval, 0f, null)
                interval += imgSelected!!.intrinsicWidth + dipToPx(intervalDip.toFloat())
            }
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {

        when (event.action) {
            MotionEvent.ACTION_UP, MotionEvent.ACTION_MOVE -> {
                currentX = event.x
                var grade = 0
                for (i in gradeNumber downTo 1) {
                    if (currentX >= xGradeList[i - 1]) {
                        grade = i
                        break
                    }
                }
                if (currentGrade != grade) {
                    currentGrade = grade
                    invalidate()
                }
            }
        }

        return true
    }
}